package com.dody.junit;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * @author ShiXin
 * @date 2019/4/19 21:42
 * @description lite-junit
 */
public class TestSuite implements Test {

    List<Test> tests = new ArrayList<>(10);

    private String name;


    public TestSuite(final Class<?> theClass) {
        this.name = theClass.getName();
        Constructor constructor = null;
        try {
            constructor = getConstructor(theClass);
        } catch (NoSuchMethodException e) {
//            addTest();
            return;
        }

        if (!Modifier.isPublic(theClass.getModifiers())) {
            return;
        }

        Vector<String> names = new Vector<>();
        Method[] methods = theClass.getDeclaredMethods();
        for (Method method : methods) {
            addTestMethod(method, names, constructor);
        }

        if (tests.size() == 0) {

        }
    }

    private Constructor getConstructor(Class<?> theClass) throws NoSuchMethodException {
        Class<?>[] args = {String.class};
        return theClass.getConstructor(args);
    }

    private void addTestMethod(Method method, Vector<String> names, Constructor constructor)  {
        String name = method.getName();
        if (names.contains(name)) {
            return;
        }
        if(isPublicTestMethod(method)){
            names.add(name);
        }

        try {
            addTest((Test) constructor.newInstance(name));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private boolean isPublicTestMethod(Method method) {
        return isTestMethod(method) && Modifier.isPublic(method.getModifiers());
    }

    private boolean isTestMethod(Method method) {
        String name = method.getName();
        Parameter[] parameters = method.getParameters();
        Class returnType = method.getReturnType();
        return parameters.length ==0 && name.startsWith("test") && returnType.equals(Void.TYPE);
    }

    @Override
    public void run() {
        for (Test test : tests) {
            test.run();
        }
    }

    public void addTest(Test test) {
        tests.add(test);
    }
}
